/*
 * acooly.cn Inc.
 * Copyright (c) 2016 All Rights Reserved.
 * create by zhangpu
 * date:2016年5月1日
 *
 */
package com.acooly.openapi.client.provider.fudian.support;

import com.acooly.core.utils.Dates;
import com.acooly.core.utils.Strings;
import com.acooly.core.utils.mapper.CsvMapper;
import com.acooly.module.openapi.client.api.enums.ApiMessageType;
import com.acooly.test.AcoolyCoder;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.util.Date;
import java.util.List;

/**
 * 简单API报文生成器
 *
 * @author zhangpu
 */
public class FudianApiMessageBuilder {

    // 报文CSV文件目录
    static private String messagesPath = "/openapi-client-test/src/test/resources/message/fudian/other";
    // 目标工程workspace（到java文件夹的目录）
    static String workspace = "/openapi-client-provider-fudian" +
            "/src/main/java/";

    static String AUTHOR = "zhangpu";
    static String FILE_NAME = "query_downloadLogFiles_response.csv";
    static String EXCLUDE_FILEDS = "orderDate,orderNo,returnUrl,notifyUrl,extMark";
    static String classPath = "com.acooly.module.openapi.client.provider.fudian.message.other";


    public static void main(String[] args) throws Exception {


//        String path = AcoolyCoder.getProjectPath() + messagesPath + SUB_PATH;
//        Iterator<File> fileIterator = FileUtils.iterateFiles(new File(path), null, false);
//        File file = null;
//        while (fileIterator.hasNext()) {
//            file = fileIterator.next();
//            genApiMessage(file.getName());
//        }
        genApiMessage(FILE_NAME);
    }

    public static void genApiMessage(String fileName)
            throws Exception {

        String serviceName = Strings.substringBeforeLast(fileName, "_");
        ApiMessageType messageType = ApiMessageType.Request;
        if (fileName.contains("notify")) {
            messageType = ApiMessageType.Notify;

        } else if (fileName.contains("request")) {
            messageType = ApiMessageType.Request;

        } else if (fileName.contains("response")) {
            messageType = ApiMessageType.Response;
        } else if (fileName.contains("return")) {
            messageType = ApiMessageType.Return;
        } else {
            throw new RuntimeException("文件名不规范");
        }


        String className = getCanonicalClassName(serviceName, messageType);
        List<String> lines = readLines(AcoolyCoder.getProjectPath() + messagesPath + "/" + fileName);
        StringBuilder sb = new StringBuilder();
        sb.append("/*\n" +
                " * www.acooly.cn Inc.\n" +
                " * Copyright (c) 2018 All Rights Reserved\n" +
                " */\n" +
                "\n" +
                "/*\n" +
                " * 修订记录:\n" +
                " * " + AUTHOR + "@acooly.cn " + Dates.format(new Date(), Dates.CHINESE_DATETIME_FORMAT_LINE) + " 创建\n" +
                " */");
        sb.append("package ").append(classPath).append(";\r\n")
                .append("\nimport com.acooly.module.openapi.client.api.enums.ApiMessageType;")
                .append("\nimport com.acooly.module.openapi.client.provider.fudian.domain.FudianApiMsg;")
                .append("\nimport com.acooly.module.openapi.client.provider.fudian.enums.FudianServiceNameEnum;")
                .append("\nimport com.acooly.module.openapi.client.provider.fudian.domain.Fudian" + messageType.code() + ";")

                .append("\n\nimport lombok.Getter;\n" +
                        "import lombok.Setter;")
                .append("\nimport org.hibernate.validator.constraints.Length;")
                .append("\nimport org.hibernate.validator.constraints.NotEmpty;")
                .append("\n\n")

                .append("/**\n" +
                        " * @author " + AUTHOR + " " + Dates.format(new Date(), Dates.CHINESE_DATETIME_FORMAT_LINE) + "\n" +
                        " */\n" +
                        "@Getter\n" +
                        "@Setter\n")
                .append("@FudianApiMsg(service = FudianServiceNameEnum.").append(Strings.upperCase(serviceName)).append(" ,type = ApiMessageType." + messageType.name())
                .append(")\n")
                .append("public class ").append(className).append(" extends Fudian").append(messageType.code())
                .append(" {\n");
        String itemDeclare = null;
        for (String line : lines) {
            itemDeclare = generateItemDeclare(line);
            if (itemDeclare != null) {
                sb.append(itemDeclare);
            }

        }
        sb.append("}");
        String targetPath = workspace + Strings.replace(classPath, ".", "/");
        targetPath = AcoolyCoder.getProjectPath() + targetPath + "/" + className + ".java";
        System.out.println(targetPath);
        FileUtils.write(new File(targetPath), sb.toString(), "UTF-8");
    }

    private static List<String> readLines(String filePath) throws Exception {
        return FileUtils.readLines(new File(filePath));
    }


    private static String generateItemDeclare(String line) {
        String[] items = CsvMapper.unmarshal(line).toArray(new String[]{});
        String itemName = Strings.trimToEmpty(items[1]);
        String title = Strings.trimToEmpty(items[0]);
//		String dataType = Strings.trimToEmpty (items[2]);
        String length = Strings.trimToEmpty(items[2]);
        String required = Strings.trimToEmpty(items[3]);
        String comments = Strings.trimToEmpty(items[4]);

        if (Strings.contains(EXCLUDE_FILEDS, itemName)) {
            return null;
        }

        StringBuilder sb = new StringBuilder();
        // 备注
        sb.append("\n    /**\n ").append("    * ").append(title).append("\n");
        sb.append("     * ").append(comments).append("\n");
        sb.append("     */\n");

        // 必选
        if (required.equals("必填")) {
            sb.append("    @NotEmpty").append("\n");
        }

        if (isFixSize(length)) {
            sb.append("    @Length(min = ").append(getSize(length)).append(",max=").append(getSize(length)).append(")\n");
        } else {
            sb.append("    @Length(max=").append(getSize(length)).append(")\n");
        }

        sb.append("    private String ").append(getCanonicalFieldName(itemName)).append(";\n");
        return sb.toString();
    }


    private static String getSize(String length) {
        StringBuilder sb = new StringBuilder();
        for (char c : length.toCharArray()) {
            if (Character.isDigit(c)) {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    private static boolean isFixSize(String length) {
        return Strings.startsWith(length, "定长");
    }

    private static String getCanonicalFieldName(String itemName) {
        if (Strings.contains(itemName, "_")) {
            String[] is = Strings.split(itemName, "_");
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < is.length; i++) {
                if (i == 0) {
                    sb.append(is[i]);
                } else {
                    sb.append(Strings.capitalize(is[i]));
                }
            }
            return sb.toString();
        } else {
            return itemName;
        }
    }

    private static String getCanonicalClassName(String serviceName, ApiMessageType apiMessageType) {
        String temp = Strings.lowerCase(serviceName);
        temp = getCanonicalFieldName(temp);
        temp = Strings.capitalize(temp) + apiMessageType.code();
        return temp;
    }

}
